﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using IssueVision.Data.Web;
using IssueVision.Common;

namespace IssueVision.Model
{
    [Export(typeof(IPasswordResetModel))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class PasswordResetModel : IPasswordResetModel
    {
        #region "Private Data"
        private PasswordResetContext _ctx;
        #endregion "Private Data"

        #region "Protected Propertes"
        protected PasswordResetContext Context
        {
            get
            {
                if (_ctx == null)
                {
                    _ctx = new PasswordResetContext();
                    _ctx.PropertyChanged += _ctx_PropertyChanged;
                }

                return _ctx;
            }
        }
        #endregion "Protected Propertes"

        #region "IPasswordResetModel Interface implementation"
        /// <summary>
        /// Call GetUserByName
        /// </summary>
        /// <param name="name"></param>
        public void GetUserByNameAsync(string name)
        {
            PerformQuery(Context.GetUserByNameQuery(name), GetUserComplete);
        }

        /// <summary>
        /// Call UpdateUser to submit changes
        /// </summary>
        public void SaveUserAsync()
        {
            Context.SubmitChanges(s =>
                {
                    if (SaveUserComplete != null)
                    {
                        try
                        {
                            Exception ex = null;
                            if (s.HasError)
                            {
                                ex = s.Error;
                                s.MarkErrorAsHandled();
                            }
                            SaveUserComplete(this, new ResultsArgs(ex));
                        }
                        catch (Exception ex)
                        {
                            SaveUserComplete(this, new ResultsArgs(ex));
                        }
                    }
                }, null);
        }

        /// <summary>
        /// Reject any pending changes
        /// </summary>
        public void RejectChanges()
        {
            Context.RejectChanges();
        }

        /// <summary>
        /// True if either "IsLoading" or "IsSubmitting" is
        /// in progress; otherwise, false
        /// </summary>
        public Boolean IsBusy
        {
            get
            {
                return _isBusy;
            }

            private set
            {
                if (_isBusy != value)
                {
                    _isBusy = value;
                    OnPropertyChanged("IsBusy");
                }
            }
        }
        private Boolean _isBusy;

        public event EventHandler<EntityResultsArgs<PasswordResetUser>> GetUserComplete;
        public event EventHandler<ResultsArgs> SaveUserComplete;
        #endregion "IPasswordResetModel Interface implementation"

        #region "INotifyPropertyChanged Interface implementation"
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion "INotifyPropertyChanged Interface implementation"

        #region "Private Methods"
        private void _ctx_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsLoading":
                    IsBusy = _ctx.IsLoading;
                    break;
                case "IsSubmitting":
                    IsBusy = _ctx.IsSubmitting;
                    break;
            }
        }

        private void PerformQuery<T>(EntityQuery<T> qry, EventHandler<EntityResultsArgs<T>> evt) where T : Entity
        {
            Context.Load(qry, LoadBehavior.RefreshCurrent, r =>
            {
                if (evt != null)
                {
                    try
                    {
                        if (r.HasError)
                        {
                            evt(this, new EntityResultsArgs<T>(r.Error));
                            r.MarkErrorAsHandled();
                        }
                        else if (r.Entities.Count() > 0)
                        {
                            evt(this, new EntityResultsArgs<T>(r.Entities));
                        }
                        else
                        {
                            var ex = new Exception(CommonResources.NoUserFound);
                            evt(this, new EntityResultsArgs<T>(ex));
                        }
                    }
                    catch (Exception ex)
                    {
                        evt(this, new EntityResultsArgs<T>(ex));
                    }
                }
            }, null);
        }
        #endregion "Private Methods"
    }
}
